package com.seckill.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.seckill.mapper.SeckillActivityMapper;
import com.seckill.mapper.SeckillCouponMapper;
import com.seckill.mapper.VoucherOrderMapper;
import com.seckill.pojo.dto.VoucherOrderSubmitDTO;
import com.seckill.pojo.entity.SeckillActivity;
import com.seckill.pojo.entity.VoucherOrder;
import com.seckill.pojo.vo.VoucherOrderVo;
import com.seckill.service.SeckillActivityService;
import com.seckill.service.SeckillCouponService;
import com.seckill.utils.RedisIdWorker;
import com.sky.context.BaseContext;
import com.seckill.pojo.entity.SeckillCoupon;
import com.sky.exception.BusinessException;
import com.sky.result.PageResult;
import lombok.extern.slf4j.Slf4j;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Collections;

@Service
@Transactional
@Slf4j
public class SeckillCouponServiceImpl extends ServiceImpl<VoucherOrderMapper, VoucherOrder> implements SeckillCouponService {

    @Autowired
    private SeckillCouponMapper seckillCouponMapper;

    @Autowired
    private SeckillActivityMapper seckillActivityMapper;

    @Autowired
    private SeckillActivityService seckillActivityService;

    private static final DefaultRedisScript<Long> Seckill_SCRIPT;

    static {
        Seckill_SCRIPT = new DefaultRedisScript<>();
        Seckill_SCRIPT.setLocation(new ClassPathResource("mqLua.lua"));
        Seckill_SCRIPT.setResultType(Long.class);
    }

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private RedisIdWorker redisIdWorker;

    @Override
    public void save(SeckillCoupon seckillCoupon) {

    }

    @Override
    public PageResult pageQuery(int page, int pageSize, Long activityId) {
        return null;
    }

    @Override
    public SeckillCoupon getById(Long id) {
        SeckillCoupon seckillCoupon = seckillCouponMapper.getById(id);
        return seckillCoupon;
    }

    @Override
    public void update(SeckillCoupon seckillCoupon) {

    }

    @Override
    public void delete(Long id) {

    }

    /**
     * 上架优惠券到活动
     *
     * @param couponId   优惠券ID
     * @param activityId 活动ID
     */
    @Override
    public void addToActivity(Long couponId, Long activityId) {
        log.info("上架优惠券到活动：优惠券ID={}，活动ID={}", couponId, activityId);

        // 1. 校验优惠券是否存在
        SeckillCoupon coupon = seckillCouponMapper.getById(couponId);
        if (coupon == null) {
            throw new BusinessException("优惠券不存在");
        }

        // 2. 校验活动是否存在
        SeckillActivity activity = seckillActivityService.getById(activityId);
        if (activity == null) {
            throw new BusinessException("活动不存在");
        }

        // 3. 更新优惠券的活动ID
        coupon.setActivityId(activityId);
        coupon.setUpdateTime(LocalDateTime.now());
        coupon.setUpdateUser(BaseContext.getCurrentId());

        // 4. 保存更新
        seckillCouponMapper.update(coupon);
        log.info("优惠券上架成功：{}", coupon);
    }

    /**
     * 用户领取优惠券
     *
     * @param couponId 优惠券ID
     * @param userId   用户ID
     */
    @Override
    public void take(Long couponId, Long userId) {
        log.info("用户领取优惠券：优惠券ID={}，用户ID={}", couponId, userId);

        // 1. 校验优惠券是否存在
        SeckillCoupon coupon = seckillCouponMapper.getById(couponId);
        if (coupon == null) {
            throw new BusinessException("优惠券不存在");
        }

        // 2. 校验优惠券库存
        if (coupon.getStock() <= 0) {
            throw new BusinessException("优惠券已抢光");
        }

        // 3. 校验用户是否已领取过该优惠券
        int count = seckillCouponMapper.countUserCoupon(couponId, userId);
        if (count >= coupon.getLimitCount()) {
            throw new BusinessException("已达到领取上限");
        }

        // 4. 扣减库存
        int result = seckillCouponMapper.reduceStock(couponId);
        if (result == 0) {
            throw new BusinessException("优惠券已抢光");
        }

        // 5. 保存用户领取记录
        seckillCouponMapper.userTakeCoupon(couponId, userId);
    }

    @Override
    public VoucherOrderVo seckillCouponOrder(VoucherOrderSubmitDTO voucherOrderSubmitDTO) {
        //1.获取出用户id 和优惠券id
        Long userId = 4L;//BaseContext.getCurrentId();
        Long voucherId = voucherOrderSubmitDTO.getVoucherId();
        //2用两个参数执行lua脚本
        Long result = stringRedisTemplate.execute(
                Seckill_SCRIPT,
                Collections.emptyList(),
                "4",
                voucherId.toString()
        );
        int value = result.intValue();
        if (value != 2) return null;
        SeckillCoupon seckillCoupon = getById(voucherId);
        long orderNumber = redisIdWorker.nextId("order");
        VoucherOrder voucherOrder = new VoucherOrder();
        if (seckillCoupon == null) {
            return null;
        }
        voucherOrder.setVoucherId(voucherId);
        voucherOrder.setUserId(userId);
        voucherOrder.setCreateTime(LocalDateTime.now());
        voucherOrder.setUpdateTime(LocalDateTime.now());
        voucherOrder.setStatus(1);
        voucherOrder.setOrderNumber(orderNumber);
        voucherOrder.setAmount(seckillCoupon.getPrice());
        rabbitTemplate.convertAndSend("voucherOrder.pay.topic", "voucherOrder.pay.success", voucherOrder);
        VoucherOrderVo voucherOrderVo = new VoucherOrderVo();
        voucherOrderVo.setOrderAmount(voucherOrder.getAmount());
        voucherOrderVo.setVoucherName(seckillCoupon.getName());
        voucherOrderVo.setOrderTime(voucherOrder.getCreateTime());
        voucherOrderVo.setOrderNumber(voucherOrder.getOrderNumber());
        voucherOrderVo.setId(voucherOrder.getId());
        return voucherOrderVo;
    }

    @Override
    public boolean decStock(Long id) {
        Boolean result =seckillCouponMapper.decStock(id);
        return result;
    }


}
